<!DOCTYPE html>
<body>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<div id="sample"></div>
<script>
function valueMissingFor(html) {
  var sample = document.getElementById('sample');
  sample.innerHTML = html;
  return sample.firstChild.validity.valueMissing;
}

test(() => {
  assert_true(valueMissingFor('<input required>'));
}, 'Empty-value INPUT[required] should be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<input value="something" required>'));
}, 'INPUT[required] with a non-empty value should not be valueMissing.');

test(() => {
  assert_true(valueMissingFor('<textarea required></textarea>'));
}, 'Empty value TEXTAREA[required] should be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<textarea required>something</textarea>'));
}, 'TEXTAREA[required] with a non-empty value should not be valueMissing.');

test(() => {
  assert_true(valueMissingFor('<select required></select>'));
}, 'SELECT[required] with no OPTIONS should be valueMissing.');

test(() => {
  assert_true(valueMissingFor('<select required>' +
    '<option value="" selected />' +
    '<option value="X">X</option>' +
    '</select>'));
}, 'SELECT[required] with a selected placeholder OPTION should be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<select required>' +
    '<option value="X">X</option>' +
    '<option value="" selected />' +
    '</select>'));
}, 'SELECT[required] with a selected non-placeholder OPTION should not be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<select size="2" required>' +
    '<option value="" selected />' +
    '<option value="X">X</option>' +
    '</select>'));
}, 'SELECT[required][size=2] with a selected placeholder OPTION should not be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<select size="2" required>' +
    '<option value="X">X</option>' +
    '<option value="" selected />' +
    '</select>'));
}, 'SELECT[rquired][size=2] with a selected non-placeholder OPTION should not be valueMissing.');

test(() => {
  assert_true(valueMissingFor('<select multiple required>' +
    '<option value="" />' +
    '<option value="X">X</option>' +
    '</select>'));
}, 'SELECT[required][multiple] without selected OPTIONs should be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<select multiple required>' +
    '<option value="" selected />' +
    '<option value="X">X</option>' +
    '</select>'));
}, 'SELECT[required][multiple] with a selected placeholder-like OPTION should not be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<select multiple required>' +
    '<option value="X">X</option>' +
    '<option value="" selected />' +
    '</select>'));
}, 'SELECT[required][multiple] with a selected OPTION should not be valueMissing.');

test(() => {
  assert_true(valueMissingFor('<select multiple size="2" required>' +
    '<option value="" />' +
    '<option value="X">X</option>' +
    '</select>'));
}, 'SELECT[required][multiple][size=2] without selected OPTIONs should be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<select multiple size="2" required>' +
    '<option value="" selected />' +
    '<option value="X">X</option>' +
    '</select>'));
}, 'SELECT[required][multiple][size=2] with a selected placeholder-liek OPTION should not be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<select multiple size="2" required>' +
    '<option value="X">X</option>' +
    '<option value="" selected />' +
    '</select>'));
}, 'SELECT[required][multiple][size=2] with a selected OPTION should not be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<select required>' +
    '<optgroup label="1">' +
    '  <option value="" selected />' +
    '</optgroup>' +
    '<option value="X">X</option>' +
    '</select>'));
}, 'SELECT[required] with a selected placeholder-like OPTION inside an OPTGROUP should not be valueMissing.');

test(() => {
  assert_true(valueMissingFor('<select required>' +
    '<option value="" disabled selected />' +
    '<option value="X">X</option>' +
    '</select>'));
}, 'SELECT[required] with a selected disabled placeholder OPTION should be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<select id="select-disabled-option-2" required>' +
    '<option value="" disabled />' +
    '<option value="X">X</option>' +
    '</select>'));
  assert_equals(document.getElementById('select-disabled-option-2').selectedIndex, 1);
}, 'SELECT[required] with a non-selected disabled placeholder OPTION should not be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<select required>' +
    '<option value="" />' +
    '<option value="X" selected>X</option>' +
    '</select>'));
}, 'SELECT[required] with a unselected placeholder OPTION should not be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<select size="2" required>' +
    '<option value="" />' +
    '<option value="X" selected>X</option>' +
    '</select>'));
}, 'SELECT[required][size=2] with a unselected placeholder OPTION should not be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<select size="2" required>' +
    '<option value="X" selected>X</option>' +
    '<option value="" />' +
    '</select>'));
}, 'SELECT[required][size=2] with a unselected placeholder-like OPTION should not be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<select multiple required>' +
    '<option value="" />' +
    '<option value="X" selected>X</option>' +
    '</select>'));
}, 'SELECT[required][multiple] with a unselected placeholder OPTION should not be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<select multiple required>' +
    '<option value="X" selected>X</option>' +
    '<option value="" />' +
    '</select>'));
}, 'SELECT[required][multiple] with a unselected placeholder-like OPTION should not be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<select multiple size="2" required>' +
    '<option value="" />' +
    '<option value="X" selected>X</option>' +
    '</select>'));
}, 'SELECT[required][size=2][multiple] with a unselected placeholder OPTION should not be valueMissing.');

test(() => {
  assert_false(valueMissingFor('<select multiple size="2" required>' +
    '<option value="X" selected>X</option>' +
    '<option value="" />' +
    '</select>'));
}, 'SELECT[required][size=2][multiple] with a unselected placeholder-like OPTION should not be valueMissing.');

test(() => {
  assert_true(!!window.eventSender, 'Needs eventSender.');
  // Select by type-ahead.
  assert_true(valueMissingFor('<select id="select-selecting-by-key" required>' +
    '<option value="" selected/>' +
    '<option>a</option>' +
    '</select>'));
  var select = document.getElementById('select-selecting-by-key');
  select.focus();
  eventSender.keyDown('a');
  assert_equals(select.value, 'a');
  assert_false(select.validity.valueMissing);

  // Select by accesskey.
  assert_true(valueMissingFor('<select id="select-selecting-by-key-2" required>' +
    '<option value="" selected/>' +
    '<option accesskey="1">a</option>' +
    '</select>'));
  select = document.getElementById('select-selecting-by-key-2');
  select.focus();
  eventSender.keyDown('1', 'accessKey');
  assert_equals(select.value, 'a');
  assert_false(select.validity.valueMissing);
}, 'Updating valueMissing state by user input.');

test(() => {
  document.querySelector('#sample').innerHTML =
    '<fieldset id="non-supported-container">' +
    '<input name="victim" type="hidden" required />' +
    '<input name="victim" type="range" required />' +
    '<input name="victim" type="image" required />' +
    '<input name="victim" type="reset" required />' +
    '<input name="victim" type="button" required />' +
    '<input name="victim" type="submit" required />' +
    '</fieldset>';
  var fieldset = document.querySelector('#non-supported-container');
  for (var c of fieldset.elements) {
    assert_false(c.validity.valueMissing);
  }
}, 'INPUT elements of some types never be valueMissing.');

test(() => {
  document.querySelector('#sample').innerHTML =
    '<input name="victim" type="checkbox" required checked />' +
    '<input name="victim" type="checkbox" required />';
  var controls = document.querySelectorAll('input[type=checkbox]');
  assert_false(controls[0].validity.valueMissing);
  assert_true(controls[1].validity.valueMissing);
}, 'INPUT[type=checkbox] supports valueMissing.');

test(() => {
  assert_true(valueMissingFor('<input type="file" required />'));
}, 'INPUT[type=file] supports valueMissing.');

test(() => {
  assert_true(valueMissingFor('<input type="text" required />'));
}, 'INPUT[type=text] supports valueMissing.');

test(() => {
  assert_true(valueMissingFor('<input type="search" required />'));
}, 'INPUT[type=search] supports valueMissing.');

test(() => {
  assert_true(valueMissingFor('<input type="url" required />'));
}, 'INPUT[type=url] supports valueMissing.');

test(() => {
  assert_true(valueMissingFor('<input type="tel" required />'));
}, 'INPUT[type=tel] supports valueMissing.');

test(() => {
  assert_true(valueMissingFor('<input type="email" required />'));
}, 'INPUT[type=email] supports valueMissing.');

test(() => {
  assert_true(valueMissingFor('<input type="password" required />'));
}, 'INPUT[type=password] supports valueMissing.');

test(() => {
  assert_true(valueMissingFor('<input type="number" required />'));
}, 'INPUT[type=number] supports valueMissing.');
</script>
</body>
